﻿//#define  UIDEBUG

using System.Reflection;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LiveCharts;
using TcpService;

namespace EC3_6CLH.Model
{
    public partial class WorkstationModel : ObservableObject
    {
        public WorkstationModel(int id, string ip, int port, TimeSpan time)
        {
            Id = id;
            Ip = ip;
            Port = port;
            GoalTime = time;
        }

        [ObservableProperty] private int _id;
        [ObservableProperty] private string _ip;
        [ObservableProperty] private int _port;
        [ObservableProperty] private WorkstationState _workstationState;
        [ObservableProperty] private TimeSpan _runTime;
        [ObservableProperty] private string _sn = "";
        [ObservableProperty] private string _displaySn1 = "";
        [ObservableProperty] private string _displaySn2 = "";
        [ObservableProperty] private bool _isLock = false;  //指示当前工位是否解锁
        [ObservableProperty] private DateTime _startTime;
        public Action<WorkstationState>? WorkstationStateChangedEvent;
        public Action<string>? LogMessageEvent;
        private EC3TcpClient EC3TcpClient;
        [ObservableProperty] private float _tempture; //温度
        [ObservableProperty] private float _axis1Current; //1轴电流
        [ObservableProperty] private float _axis2Current; //2轴电流
        [ObservableProperty] private float _axis3Current; //3轴电流
        [ObservableProperty] private float _axis4Current; //4轴电流
        [ObservableProperty] private float _axis5Current; //5轴电流
        [ObservableProperty] private float _axis6Current; //6轴电流
        [ObservableProperty] private float _axis7Current; //7轴电流
        [ObservableProperty] private float _axis8Current; //8轴电流

        private static Dictionary<UInt16, string> DictErrMessage;

        private string GetErrMessage(UInt16 key)
        {
            if (DictErrMessage.ContainsKey(key))
            {
                return DictErrMessage[key];
            }
            else
            {
                return $"错误代码[0x{key.ToString("X4")}]未找到错误信息";
            }
        }

        static WorkstationModel()
        {
            DictErrMessage = new Dictionary<ushort, string>();
            DictErrMessage.Add(0x2250, "0x2250驱动器短路");
            DictErrMessage.Add(0x2310, "0x2310U相输出电流过大");
            DictErrMessage.Add(0x2311, "0x2311最大电流限制故障");
            DictErrMessage.Add(0x2312, "0x2312W相电流输出过大");
            DictErrMessage.Add(0x3210, "0x3210直流母线过压");
            DictErrMessage.Add(0x3220, "0x3220直流母线欠压");
            DictErrMessage.Add(0x4000, "0x4000控制板过温故障");
            DictErrMessage.Add(0x4210, "0x4210功率模块过热");
            DictErrMessage.Add(0x5410, "0x5410扭矩关闭故障");
            DictErrMessage.Add(0x6010, "0x6010CPU1看门狗溢出");
            DictErrMessage.Add(0x6100, "0x6100控制环路选择故障");
            DictErrMessage.Add(0x6200, "0x6200ECAT中断时间超时故障");
            DictErrMessage.Add(0x6310, "0x6310读取参数错误");
            DictErrMessage.Add(0x6320, "0x6320电机速度参数矛盾");
            DictErrMessage.Add(0x7110, "0x7110强制抱闸错误");
            DictErrMessage.Add(0x7111, "0x7111抱闸反馈错误");
            DictErrMessage.Add(0x7112, "0x7112能耗制动电阻过载");
            DictErrMessage.Add(0x7320, "0x7320编码器配置故障");
            DictErrMessage.Add(0x7600, "0x7600存储参数错误");
            DictErrMessage.Add(0x8311, "0x8311电机持续过载");
            DictErrMessage.Add(0x8611, "0x8611位置跟随误差过大");
            DictErrMessage.Add(0x8800, "0x8800第一编码器数据溢出");
            DictErrMessage.Add(0xFF05, "0xFF05磁极定位错误");
            DictErrMessage.Add(0xFF06, "0xFF06编码器数据异常");
            DictErrMessage.Add(0xFF07, "0xFF07编码器通信异常");
            DictErrMessage.Add(0xFF08, "0xFF08编码器通信超时");
            DictErrMessage.Add(0xFF09, "0xFF09编码器内部异常1");
            DictErrMessage.Add(0xFF10, "0xFF10驱动器其它轴异常");
            DictErrMessage.Add(0xFF11, "0xFF11电机抱闸断线");
            DictErrMessage.Add(0xFF15, "0xFF15驱动器持续过载");
            DictErrMessage.Add(0xFF17, "0xFF17驱动器输出缺相");
            DictErrMessage.Add(0xFF26, "0xFF26控制电源欠压");
            DictErrMessage.Add(0xFF27, "0xFF27STO1触发");
            DictErrMessage.Add(0xFF28, "0xFF28STO2触发");
            DictErrMessage.Add(0xFF31, "0xFF31电机超速");
            DictErrMessage.Add(0xFF34, "0xFF34速度跟随误差过大");
            DictErrMessage.Add(0xFF37, "0XFF37EtherCAT过程数据错误");
            DictErrMessage.Add(0xFF48, "0xFF48动态制动过载");
            DictErrMessage.Add(0xFF53, "0xFF53编码器过热");
            DictErrMessage.Add(0xFF54, "0xFF54编码器电池欠电压故障");
            DictErrMessage.Add(0xFF57, "0xFF57控制模式设定错误");
            DictErrMessage.Add(0xFF60, "0xFF60电机堵转");
            DictErrMessage.Add(0xFF65, "0xFF65制动模块故障");
            DictErrMessage.Add(0xFF80, "0xFF80主电源掉电");
            DictErrMessage.Add(0xFF97, "0xFF97转矩波动超限");
            DictErrMessage.Add(0xFFB0, "0xFFB0PLL错误");
            DictErrMessage.Add(0xFFB1, "0xFFB1RxPDO丢失");
            DictErrMessage.Add(0xFFB2, "0xFFB2Ecat-Port0端口丢失");
            DictErrMessage.Add(0xFFB3, "0xFFB3Ecat-Port1端口丢失");
            DictErrMessage.Add(0xFFB4, "0xFFB4驱动拒绝通信周期值");
            DictErrMessage.Add(0xFFB5, "0xFFB5Ecat-Port0端口无链接");
            DictErrMessage.Add(0xFFB6, "0xFFB6PDO映射错误");
            DictErrMessage.Add(0xFFB7, "0xFFB7PDO分配错误");
            DictErrMessage.Add(0xFFB8, "0xFFB8同步事件超差");
            DictErrMessage.Add(0xFFB9, "0xFFB9同步事件丢失");
            DictErrMessage.Add(0xFFBA, "0xFFBACSP/CSV/CST模式请求错误");
            DictErrMessage.Add(0xFFBB, "0xFFBBPP模式请求错误");
            DictErrMessage.Add(0xFFBC, "0xFFBCPV模式请求错误");
            DictErrMessage.Add(0xFFC0, "0xFFC0制动电阻泄放异常");
            DictErrMessage.Add(0xFFC2, "0XFFC2数字IO错误");
            DictErrMessage.Add(0xFFC3, "0XFFC3硬件型号错误");
            DictErrMessage.Add(0xFFC4, "0XFFC4自整定故障");
            DictErrMessage.Add(0xFFC5, "0xFFC5风扇模块异常");
            DictErrMessage.Add(0xFFC6, "0xFFC6电机I2T故障");
            DictErrMessage.Add(0xFFC7, "0xFFC7DC电压预充故障");
            DictErrMessage.Add(0xFFC8, "0xFFC8载波周期配置故障");
            DictErrMessage.Add(0xFFC9, "0xFFC9自举失败故障");
            DictErrMessage.Add(0xFFCA, "0xFFCA转矩限制故障");
            DictErrMessage.Add(0xFFD0, "0xFFD0电机位置传感器错误.第一次上电初始化");
            DictErrMessage.Add(0xFFD1, "0xFFD1电机位置传感器请求上电.未初始化");
            DictErrMessage.Add(0xFFD2, "0xFFD2编码器参数位数报警");
            DictErrMessage.Add(0xFFD3, "0xFFD3编码器多圈计数错误");
            DictErrMessage.Add(0xFFD7, "0xFFD7三相阈值未更新故障");
            DictErrMessage.Add(0xFFCB, "0xFFCB零偏电流过大");
            DictErrMessage.Add(0x2716, "0x2716编码器初始化失败");
            DictErrMessage.Add(0xFF22, "0xFF22位置目标值异常");
        }

        partial void OnWorkstationStateChanged(WorkstationState value)
        {
            WorkstationStateChangedEvent?.Invoke(value);
        }

        partial void OnSnChanged(string value)
        {
            if (value.Length>10)
            {
                DisplaySn1 = Sn.Substring(0, 10);
                DisplaySn2 = Sn.Substring(10);
            }
            else
            {
                DisplaySn1 = Sn;
                DisplaySn2 = "";
            }
        }

        /// <summary>
        /// 运行的目标时长
        /// </summary>
        public TimeSpan GoalTime { get; init; }

        private async Task DelayAsync(int millSeconds, CancellationToken ct = default(CancellationToken))
        {
            try
            {
                await Task.Delay(millSeconds, ct);
            }
            catch (OperationCanceledException) // 精准捕获取消异常
            {
                throw new OperationCanceledException($"工位[{Id}]操作被取消", ct); // 传递原始Token
            }
        }

        /// <summary>
        /// 开始计时
        /// </summary>
        private async Task StartTiming()
        {
            StartTime = DateTime.Now;
            WorkstationState = WorkstationState.Running;

            while (WorkstationState == WorkstationState.Running)
            {
                RunTime = DateTime.Now - StartTime;
                if (RunTime >= GoalTime)
                {
                    return;
                }
                await DelayAsync(1000);
            }
        }

        private async Task Initialize(CancellationToken ct = default(CancellationToken))
        {
            LogMessageEvent?.Invoke($"工位{Id}初始化开始");

            WorkstationState = WorkstationState.Initializing;
            EC3TcpClient = new EC3TcpClient(Ip);
            var pingResult = await PingChecker.ContinuousPing(Ip, TimeSpan.FromSeconds(200), ct);

            if (!pingResult)
            {
                throw new Exception($"工位{Id}驱动器{Ip}ping result = false");
            }

            //连接产品
            await EC3TcpClient.ConnectAsync(ct);
            //read sn
            Sn = await EC3TcpClient.ReadSn(ct: ct);

            foreach (var item in GlobalValue.TestConfig.InitParams)
            {
                LogMessageEvent?.Invoke($"threadId={Thread.CurrentThread.ManagedThreadId}工位{Id}写入{item.Name}");
                await EC3TcpClient.Write(InitParam.Axis, item.Index, item.SubIndex, item.TypeValue, item.DataLen, item.DataValue, ct);
                var data = await EC3TcpClient.Read(InitParam.Axis, item.Index, item.SubIndex, item.TypeValue, item.DataLen, ct);
                if (!item.AreEqual(data))
                {
                    throw new Exception($"工位{Id}写入[{item.DataValue}],回读[{data}]");
                }
            }

            LogMessageEvent?.Invoke($"工位{Id}初始化完成");
        }

        private async Task Run(CancellationToken ct = default(CancellationToken))
        {
            //异步启动计时器
            _ = StartTiming();
            LogMessageEvent?.Invoke($"工位{Id}老化开始");
            while (WorkstationState == WorkstationState.Running)
            {
                //监控变量
                // 读温度
                Tempture = (float)await EC3TcpClient.Read(1, 0x2101, 0x0C, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct);
                // 读电流
                Axis1Current = (float)((float)await EC3TcpClient.Read(1, 0x2103, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                Axis2Current = (float)((float)await EC3TcpClient.Read(1, 0x2903, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                Axis3Current = (float)((float)await EC3TcpClient.Read(1, 0x3103, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                Axis4Current = (float)((float)await EC3TcpClient.Read(1, 0x3903, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                Axis5Current = (float)((float)await EC3TcpClient.Read(1, 0x4103, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                Axis6Current = (float)((float)await EC3TcpClient.Read(1, 0x4903, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"), ct)/1.5/1.414);
                //Axis7Current = (float)await EC3TcpClient.Read(1, 0x5103, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"));
                //Axis8Current = (float)await EC3TcpClient.Read(1, 0x5903, 0x05, InitParam.GetDataType("F32"), InitParam.GetDataLen("F32"));

                // 读报警
                for (int i = 0; i < 6; i++)
                {
                    var errcode = (UInt16)await EC3TcpClient.Read(1, (UInt16)(0x603F+i*0x0800), 0x00, InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"), ct);
                    if (errcode!=0)
                    {
                        var errMessage = GetErrMessage(errcode);
                        LogMessageEvent?.Invoke($"工位{Id}{i+1}轴{errMessage}");
                    }
                }
                // 标准IO监控
                string tmp = "";
                for (int i = 0; i < 16; i++)
                {
                    var di = (UInt16)await EC3TcpClient.Read(18, 0x6001, (ushort)(0x01+i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"), ct);
                    tmp+= $"{di} ";
                    //LogMessageEvent?.Invoke($"工位{Id} DI{i+1} = {di}");
                }
                LogMessageEvent?.Invoke($"工位{Id} 标准DI[{tmp}]");

                tmp="";
                for (int i = 0; i < 16; i++)
                {
                    var @do = (UInt16)await EC3TcpClient.Read(18, 0x7001, (ushort)(0x01+i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"), ct);
                    //LogMessageEvent?.Invoke($"工位{Id} DO{i+1} = {di}");
                    tmp+= $"{@do} ";
                }
                LogMessageEvent?.Invoke($"工位{Id} 标准DO[{tmp}]");

                // 拓展IO监控
                tmp="";
                for (int j = 0; j < 4; j++)
                {
                    for (int i = 0; i < 16; i++)
                    {
                        var di = (UInt16)await EC3TcpClient.Read(18, (ushort)(0x6010+j), (ushort)(0x01+i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"), ct);
                        tmp+= $"{di} ";
                    }
                }

                LogMessageEvent?.Invoke($"工位{Id} 扩展DI[{tmp}]");

                tmp="";
                for (int j = 0; j < 4; j++)
                {
                    for (int i = 0; i < 16; i++)
                    {
                        var @do = (UInt16)await EC3TcpClient.Read(18, (ushort)(0x7010+j), (ushort)(0x01+i), InitParam.GetDataType("U16"), InitParam.GetDataLen("U16"), ct);
                        tmp+= $"{@do} ";
                    }
                }

                LogMessageEvent?.Invoke($"工位{Id} 扩展DO[{tmp}]");

                await Task.Delay(5000);

                if (RunTime < GoalTime)
                {
#if UIDEBUG
                    if (RunTime > TimeSpan.FromSeconds(3))
                    {
                        if (id == 4)
                        {
                            WorkstationState = WorkstationState.Ng;
                            LogMessageEvent?.Invoke($"工位{id}老化失败!");
                        }
                    }
#endif
                    if (!CheckDevStatus())
                    {
                        WorkstationState = WorkstationState.Ng;
                        LogMessageEvent?.Invoke($"工位{Id}老化失败!");
                    }
                }
                else
                {
                    LogMessageEvent?.Invoke($"工位{Id}老化成功");
                    WorkstationState = WorkstationState.Ok;
                }
                await DelayAsync(10, ct);

#if UIDEBUG

                if (RunTime > TimeSpan.FromSeconds(3))
                {
                    if (id == 3)
                    {
                        throw new Exception("hello error");
                    }
                }
#endif
            }

            // 记录测试报告
        }

        //校验驱动器状态
        private bool CheckDevStatus()
        {
            return true;
        }

        private CancellationTokenSource _stopCancellationTokenSource = new CancellationTokenSource();

        #region Public

        public void Reset()
        {
            if (IsLock)
            {
                return;
            }
            if (WorkstationState == WorkstationState.Initializing || WorkstationState == WorkstationState.Running)
            {
                return;
            }
            WorkstationState = WorkstationState.Idle;
            RunTime = TimeSpan.FromSeconds(0);
        }

        [RelayCommand]
        public async Task StartTestAsync()
        {
            await Task.Run(async () =>
            {
                if (IsLock)
                {
                    return;
                }
                if (WorkstationState == WorkstationState.Initializing || WorkstationState == WorkstationState.Running
                   || WorkstationState == WorkstationState.Error)
                {
                    return;
                }
                _stopCancellationTokenSource = new CancellationTokenSource();
                await StartTest(_stopCancellationTokenSource.Token);
            });
        }

        [RelayCommand]
        public async Task StopAsync()
        {
            _stopCancellationTokenSource.Cancel();
            await Task.Delay(10);
        }

        #endregion Public

        private async Task StartTest(CancellationToken ct = default(CancellationToken))
        {
            try
            {
                await Initialize(ct);
                await Run(ct);
            }
            catch (OperationCanceledException)
            {
                LogMessageEvent?.Invoke($"工位{Id}停止");
                WorkstationState = WorkstationState.Stop; // 取消时重置状态
            }
            catch (Exception e)
            {
                LogMessageEvent?.Invoke($"工位{Id}发生错误[{e.Message}]!");
                WorkstationState = WorkstationState.Error;
            }
        }
    }
}